package MainPackage;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;

import org.jgrapht.UndirectedGraph;
import org.jgrapht.graph.DefaultEdge;

public class DataSet {

	/**
	 * @param args
	 * @throws FileNotFoundException
	 */
	public static void main(String[] args) throws FileNotFoundException {

		System.out.println("DataSet: Starting program..");
		long startTime = System.currentTimeMillis();
		try {

			// Get a Graph class Handle.
			GraphM graphManip = new GraphM();

			// Write the output test file.
			File oFile = new File(Settings.HOMEPATH + "\\" + Settings.TESTFILE);
			FileWriter fileStream = new FileWriter(oFile);
			BufferedWriter out = new BufferedWriter(fileStream);

			// Create a Graph with the input nodes.
			UndirectedGraph<String, DefaultEdge> stringGraph = graphManip
					.createStringGraph();

			// Nodes in the give graph.
			Set<String> vertices = stringGraph.vertexSet();
			
			// Write them to a string array for random
			// access.
			String[] vertexArray = new String[Settings.NEIGHNODESCOUNT];
			int i = 0;
			for (String vertex : vertices) {
				vertexArray[i] = vertex;
				i++;
			}
			
			Random rand = new Random(System.currentTimeMillis());
			
			// Total no. of records generated so far.
			int testRecords = 0;
			
			// Total no. of records looked so far.
			int totalEdgesLooked = 0;
			boolean complete = false;
			
			// Keep all the removed edges in a hash set so that we can
			// remove them from the original data file at the end.
			Set<DefaultEdge> removedEdges = new HashSet<DefaultEdge>();
			
			// Repeat until we get the specified number of test records.
			// We keep repeating on the same edgeSets if we reach the 
			// end of the edgeSet. We pick a random vertex each iteration.
			while (true) {
				Set<DefaultEdge> edgeSet = stringGraph.edgeSet();
				for (DefaultEdge currEdge : edgeSet) {
					String vertexA = stringGraph.getEdgeSource(currEdge);
					String vertexB = stringGraph.getEdgeTarget(currEdge);
					String vertexC = vertexArray[rand
							.nextInt(vertexArray.length)];
					totalEdgesLooked++;
					
					// If AB is an edge and A is connected to C and B is 
					// connected to C, then remove AB and keep it in the 
					// list of test data so that we can predict it later.
					if (stringGraph.containsEdge(vertexA, vertexC)
							&& stringGraph.containsEdge(vertexB, vertexC)
							&& !removedEdges.contains(currEdge)) {
						
						// We cannot remove the edge directly from the graph
						// because it is not allowed to do so when we are 
						// iterating in the loop as per the data structure.
						// stringGraph.removeEdge(vertexA, vertexB);
						removedEdges.add(currEdge);
						out.write(vertexA + "," + vertexB);
						out.newLine();
						if (testRecords++ == Settings.TESTSIZE) {
							complete = true;
							break;
						}
						if (testRecords % 1000 == 0) {
							System.out.println("Created " + testRecords
									+ " test records of "+totalEdgesLooked+"so far..");
						}
					}
				}
				if (complete) {
					break;
				}
			}
			
			out.close();
			
			// Now remove the edges from the original data file.
			
			Iterator<DefaultEdge> iter = removedEdges.iterator();
			while (iter.hasNext()) {
			  stringGraph.removeEdge(iter.next());
			}
			
			// Write the output train file.
			File oTrainFile = new File(Settings.HOMEPATH + "\\" + Settings.TRAINFILE);
			FileWriter trainFileStream = new FileWriter(oTrainFile);
			BufferedWriter trainOut = new BufferedWriter(trainFileStream);
			
			Set<DefaultEdge> finalEdges = stringGraph.edgeSet();
			for(DefaultEdge currEdge : finalEdges){
				trainOut.write(stringGraph.getEdgeSource(currEdge)+","+stringGraph.getEdgeTarget(currEdge));
				trainOut.newLine();
			}
			
			trainOut.close();
			
		} catch (Throwable ex) {
			System.err.println("Uncaught exception - " + ex.getMessage());
			ex.printStackTrace(System.err);
		}

		long endTime = System.currentTimeMillis();
		long totalTime = endTime - startTime;
		System.out.println("Total run time: " + (totalTime / 1000) + "s");
		System.out.println("Program completed succesfully.");
	}

}
